﻿using System;
using System.Data;
using Viyi.Util.Data;
using Xunit;
using Xunit.Abstractions;

namespace Viyi.Util.Test.Data
{
    public class TestDataRowUtil
    {
        DataTable data;
        ITestOutputHelper output;

        public TestDataRowUtil(ITestOutputHelper output)
        {
            this.output = output;
            CreateTable();
        }

        void CreateTable()
        {
            data = new DataTable();
            data.Columns.AddRange(new[] {
                new DataColumn("stringField", typeof(string)),
                new DataColumn("intField", typeof(int)),
                new DataColumn("longField", typeof(long)),
                new DataColumn("dateField", typeof(DateTime))
            });

            var row = data.NewRow();
            row[0] = row[1] = DBNull.Value;
            data.Rows.Add(row);

            row = data.NewRow();
            row[0] = $"S_{17:X3}";
            row[1] = int.MaxValue;
            row[2] = long.MaxValue;
            row[3] = DateTime.Today;
            data.Rows.Add(row);

            row = data.NewRow();
            row[2] = (long) int.MaxValue;
            data.Rows.Add(row);
        }

        [Fact]
        void TestValue()
        {
            var nullRow = data.Rows[0];
            Assert.Null(nullRow.Value<string>(0));
            Assert.Null(nullRow.Value<int?>(0));
            Assert.Null(nullRow.Value<long?>("longField"));
            Assert.Null(nullRow.Value<DateTime?>("dateField"));

            var vRow = data.Rows[1];
            Assert.Equal("S_011", vRow.StringValue(0));
            Assert.Equal(int.MaxValue, vRow.Value<int>(1));
            Assert.Equal((long) int.MaxValue, vRow.Value<long>("intField"));
            Assert.Equal(long.MaxValue, vRow.Value<long?>("longField"));

            // the value is too big to int type, so `default(int?)` should be returned
            Assert.Null(vRow.Value<int?>(2));
            Assert.Equal(DateTime.Today, vRow.Value<DateTime>(3));
            Assert.Equal(DateTime.Today, vRow.Value<DateTime?>("dateField"));

            var thridRow = data.Rows[2];
            // the value is in int range, so the int value should be returned;
            Assert.Equal(int.MaxValue, thridRow.Value<int?>(2));
        }
    }
}
